﻿namespace EasyWeb.Test
{
    using System;
    using System.Data.Entity;
    using System.Linq;
    using System.Threading.Tasks;
    using EasyWeb.Data;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class EWSelectionDefinitionDao_Test : LibraryTest
    {
        [TestMethod]
        public async Task Select_Test()
        {
            var expecteds = new ew_tbl_selections[2];
            expecteds[0] = CreateRawSelection("test1");
            expecteds[1] = CreateRawSelection("test2");
            await this.TestDbContext.SaveChangesAsync();
            await this.TestDbContext.Entry(expecteds[0]).ReloadAsync();
            await this.TestDbContext.Entry(expecteds[1]).ReloadAsync();

            var actuals = await this.SelectionDefinitionDao.SelectAsync();
            Assert.AreEqual(2, actuals.Count());
            foreach (var actual in actuals)
            {
                var expected = expecteds.Single(e => e.ew_uid_selection_id == actual.Id);
                Assert.IsNotNull(expected);

                Assert.AreEqual(expected.ew_uid_selection_id, actual.Id);
                Assert.AreEqual(expected.ew_vc_internal_name, actual.InternalName);
                Assert.AreEqual(expected.ew_xml_display_name, actual.DisplayName.ToText());
                Assert.AreEqual(expected.ew_dt_created.ToUtc(), actual.Created);
                Assert.AreEqual(expected.ew_nvc_created_by, actual.CreatedBy);
                Assert.AreEqual(expected.ew_dt_modified.ToUtc(), actual.Modified);
                Assert.AreEqual(expected.ew_nvc_modified_by, actual.ModifiedBy);
                CollectionAssert.AreEqual(expected.ew_t_timestamp, actual.Timestamp);
            }
        }

        [TestMethod]
        public async Task Create_Test()
        {
            var text = new EWText();
            text.Values.Add(new EWTextValue("en", "v1"));
            text.Values.Add(new EWTextValue("zh-Hans", "v2"));
            var expected = new EWSelectionDefinition()
            {
                InternalName = "test",
                DisplayName = text
            };
            await this.SelectionDefinitionDao.CreateAsync(expected);

            var actual = (await this.TestDbContext.ew_tbl_selections.ToArrayAsync()).ElementAt(0);
            Assert.AreEqual(expected.Id, actual.ew_uid_selection_id);
            Assert.AreEqual(expected.InternalName, actual.ew_vc_internal_name);
            Assert.AreEqual(expected.DisplayName.ToText(), actual.ew_xml_display_name);
            Assert.AreEqual(expected.Created, actual.ew_dt_created.ToUtc());
            Assert.AreEqual(expected.CreatedBy, actual.ew_nvc_created_by);
            Assert.AreEqual(expected.Modified, actual.ew_dt_modified.ToUtc());
            Assert.AreEqual(expected.ModifiedBy, actual.ew_nvc_modified_by);
            CollectionAssert.AreEqual(expected.Timestamp, actual.ew_t_timestamp);
        }

        [TestMethod]
        public async Task Update_Test()
        {
            var expected = CreateRawSelection("test1");
            await this.TestDbContext.SaveChangesAsync();
            await this.TestDbContext.Entry(expected).ReloadAsync();

            var actual = new EWSelectionDefinition()
            {
                Id = expected.ew_uid_selection_id,
                InternalName = "test2",
                DisplayName = expected.ew_xml_display_name.ToText(),
                Created = expected.ew_dt_created,
                CreatedBy = expected.ew_nvc_created_by,
                Modified = expected.ew_dt_modified,
                ModifiedBy = expected.ew_nvc_modified_by,
                Timestamp = expected.ew_t_timestamp
            };
            await this.SelectionDefinitionDao.UpdateAsync(actual);

            await this.TestDbContext.Entry(expected).ReloadAsync();

            Assert.AreEqual(expected.ew_uid_selection_id, actual.Id);
            Assert.AreEqual("test2", actual.InternalName);
            Assert.AreEqual(expected.ew_xml_display_name, actual.DisplayName.ToText());
            Assert.AreEqual(expected.ew_dt_created.ToUtc(), actual.Created);
            Assert.AreEqual(expected.ew_nvc_created_by, actual.CreatedBy);
            Assert.AreEqual(expected.ew_dt_modified.ToUtc(), actual.Modified);
            Assert.AreEqual(expected.ew_nvc_modified_by, actual.ModifiedBy);
            CollectionAssert.AreEqual(expected.ew_t_timestamp, actual.Timestamp);
        }

        [TestMethod]
        public async Task Delete_Test()
        {
            var expected = CreateRawSelection("test1");
            await this.TestDbContext.SaveChangesAsync();
            await this.TestDbContext.Entry(expected).ReloadAsync();

            await this.SelectionDefinitionDao.DeleteAsync(expected.ew_uid_selection_id, expected.ew_t_timestamp);

            var actual = await this.TestDbContext.ew_tbl_selections.CountAsync();
            Assert.AreEqual(0, actual);
        }

        [TestMethod]
        [ExpectedException(typeof(EWDataException))]
        public async Task CreateDuplicate_Test()
        {
            var text = new EWText();
            text.Values.Add(new EWTextValue("en", "v1"));
            text.Values.Add(new EWTextValue("zh-Hans", "v2"));
            var expected = new EWSelectionDefinition()
            {
                InternalName = "test",
                DisplayName = text
            };

            await this.SelectionDefinitionDao.CreateAsync(expected);
            await this.SelectionDefinitionDao.CreateAsync(expected);
        }

        private ew_tbl_selections CreateRawSelection(string name)
        {
            var text = new EWText();
            text.Values.Add(new EWTextValue("en", "v1"));
            text.Values.Add(new EWTextValue("zh-Hans", "v2"));
            var item = new ew_tbl_selections()
            {
                ew_uid_selection_id = Guid.NewGuid(),
                ew_dt_created = DateTime.UtcNow,
                ew_nvc_created_by = "test",
                ew_dt_modified = DateTime.UtcNow,
                ew_nvc_modified_by = "test",
                ew_vc_internal_name = name,
                ew_xml_display_name = text.ToText()
            };

            this.TestDbContext.ew_tbl_selections.Add(item);

            return item;
        }
    }
}
